﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace NGIS
{
    namespace Model
    {
        public class ModelAttribute : IModelAttribute
        {
            private List<LocalAttribute> mLocalAttributeList = new List<LocalAttribute>();
            private List<ModelCategory> mModelCategoryList = new List<ModelCategory>();

			public bool loadFromXml(XmlElement pModelClassElement)
			{
				XmlElement attributeEle = (XmlElement)pModelClassElement.ChildNodes[0];

				XmlElement categoriesEle = (XmlElement)attributeEle.ChildNodes[0];
                XmlElement localAttributesEle = (XmlElement)attributeEle.ChildNodes[1];

                foreach(var item in categoriesEle.ChildNodes)
				{
                    XmlElement childEle = item as XmlElement;
					ModelCategory modelCategory = new ModelCategory();
					modelCategory.principle = childEle.GetAttribute("principle");
					modelCategory.path = childEle.GetAttribute("path");
					mModelCategoryList.Add(modelCategory);
				}

                foreach (var item in localAttributesEle.ChildNodes)
				{
                    XmlElement childEle = item as XmlElement;
                    LocalAttribute localAttribute = new LocalAttribute();
					localAttribute.localName = childEle.GetAttribute("localName");
					localAttribute.wikiUrl = childEle.GetAttribute("wiki");
					string localTypeStr = childEle.GetAttribute("local");
					ELocalizationType localType = LocalizationHelper.String2LocalizationType(localTypeStr);
					localAttribute.localType = localType;
					XmlElement keywords_ele = (XmlElement)childEle.ChildNodes[0];
					XmlElement abstract_ele = (XmlElement)childEle.ChildNodes[1];
					string keywords_str = keywords_ele.InnerText;
					localAttribute.abstractInfo = abstract_ele.InnerText;
					
					List<string> ret=keywords_str.Split(';').ToList();
                    localAttribute.keywords = new List<string>();
					for (int iKey=0; iKey<ret.Count; iKey++)
					{
						localAttribute.keywords.Add(ret[iKey]);
					}
                }

				return true;
			}

			public bool formatToXml(XmlElement pModelClassElement)
			{
				XmlDocument doc = pModelClassElement.OwnerDocument;
				XmlElement attributeEle = doc.CreateElement("AttributeSet");

				XmlElement categoriesEle = doc.CreateElement("Categories");
				XmlElement localAttributesEle = doc.CreateElement("LocalAttributes");

				for (int i=0; i<mModelCategoryList.Count; i++)
				{
					ModelCategory temp_cate = mModelCategoryList[i];
					XmlElement temp_ele = doc.CreateElement("Category");
					temp_ele.SetAttribute("principle", temp_cate.principle);
					temp_ele.SetAttribute("path", temp_cate.path);

					categoriesEle.AppendChild(temp_ele);
				}

                for (int i = 0; i < mLocalAttributeList.Count; i++)
                {
                    LocalAttribute temp_local = mLocalAttributeList[i];
                    XmlElement temp_ele = doc.CreateElement("LocalAttribute");
                    temp_ele.SetAttribute("local", LocalizationHelper.LocalizationType2String(temp_local.localType));
                    temp_ele.SetAttribute("localName", temp_local.localName);
                    temp_ele.SetAttribute("wiki", temp_local.wikiUrl);

                    XmlElement keywordsEle = doc.CreateElement("Keywords");
                    XmlElement abstractEle = doc.CreateElement("Abstract");
                    XmlElement mechanismEle = doc.CreateElement("Mechanism");
                    XmlElement applicationEle = doc.CreateElement("Application");

                    //! Add keywords
                    string keywords_str = "";
                    for (int iKey = 0; iKey < temp_local.keywords.Count; iKey++)
                    {
                        string temp_str = temp_local.keywords[iKey];
                        keywords_str += temp_str;
                        if (iKey != temp_local.keywords.Count - 1)
                            keywords_str += "; ";
                    }
                    keywordsEle.InnerText = keywords_str;

                    //! Add abstract
                    abstractEle.InnerText = temp_local.abstractInfo;

                }
				return true;
			}

            public int getLocalAttributeCount()
            {
                return mLocalAttributeList.Count;
            }

            public bool getLocalAttribute(int idx, ref LocalAttribute pLocalAttribute)
            {
                if (idx < 0 || idx >= mLocalAttributeList.Count) return false;
                pLocalAttribute = mLocalAttributeList[idx];
                return true;
            }

            public bool getLocalAttribute(ELocalizationType pLocalType, ref LocalAttribute pLocalAttribute)
            {
                for (int i = 0; i < mLocalAttributeList.Count; i++)
                {
                    if (mLocalAttributeList[i].localType == pLocalType)
                    {
                        pLocalAttribute = mLocalAttributeList[i];
                        return true;
                    }
                }
                return false;
            }

            public bool addLocalAttributeInfo(ref LocalAttribute pLocalAttribute)
            {
                for (int i = 0; i < mLocalAttributeList.Count; i++)
                {
                    if (mLocalAttributeList[i].localType == pLocalAttribute.localType)
                    {
                        return false;
                    }
                }
                mLocalAttributeList.Add(pLocalAttribute);
                return true;
            }

            public bool removeLocalAttribute(int idx)
            {
				if (idx<0 || idx>=mLocalAttributeList.Count) return false;
                mLocalAttributeList.RemoveAt(idx);
				return true;
            }

            public bool removeLocalAttribute(ref LocalAttribute pLocalAttribute)
            {
                if (mLocalAttributeList.Contains(pLocalAttribute))
                {
                    mLocalAttributeList.Remove(pLocalAttribute);
                    return true;
                }
				return false;
            }

            public bool updateLocalAttribute(int idx, ref LocalAttribute pLocalAttribute)
            {
                if (idx < 0 || idx >= mLocalAttributeList.Count) return false;
                mLocalAttributeList[idx] = pLocalAttribute;
                return true;
            }

            public bool updateLocalAttribute(ELocalizationType pLocalType, ref LocalAttribute pLocalAttribute)
            {
                for (int i = 0; i < mLocalAttributeList.Count; i++)
                {
                    if (mLocalAttributeList[i].localType == pLocalType)
                    {
                        mLocalAttributeList[i] = pLocalAttribute;
                        return true;
                    }
                }
                return false;
            }

            public int getCategoryCount()
            {
                return mModelCategoryList.Count;
            }

            public bool getCategory(int idx, ref ModelCategory pModelCategory)
            {
                if (idx < 0 || idx >= mModelCategoryList.Count) return false;
                pModelCategory = mModelCategoryList[idx];
                return true;
            }

            public bool addCategoryInfo(ref ModelCategory pCategoryInfo)
            {
                for (int i = 0; i < mModelCategoryList.Count; i++ )
                {
                    ModelCategory it = mModelCategoryList[i];
                    if (it.principle == pCategoryInfo.principle && it.path == pCategoryInfo.path)
                    {
                        return false;
                    }
                }
				mModelCategoryList.Add(pCategoryInfo);
				return true;
            }

            public bool removeCategory(int idx)
            {
				if (idx<0 || idx>=mModelCategoryList.Count) return false;
                mModelCategoryList.RemoveAt(idx);
				return true;
            }

            public bool removeCategory(ref ModelCategory pCategoryInfo)
            {
                if (mModelCategoryList.Contains(pCategoryInfo))
                {
                    mModelCategoryList.Remove(pCategoryInfo);
                    return true;
                }
				return false;
            }

            public bool updateCategory(int idx, ref ModelCategory pCategoryInfo)
            {
                if (idx < 0 || idx >= mModelCategoryList.Count) return false;
                mModelCategoryList[idx] = pCategoryInfo;
                return true;
            }

            public bool compareOther(IModelAttribute pAttribute, ref string obj, ref string name)
            {
                if (pAttribute.getCategoryCount() != mModelCategoryList.Count)
                {
                    obj = "Categories";
                    name = "CategoryCount";
                    return false;
                }
                for (int i = 0; i < mModelCategoryList.Count; i++)
                {
                    ModelCategory temp_cate1 = mModelCategoryList[i];
                    ModelCategory temp_cate2 = new ModelCategory();
                    pAttribute.getCategory(i, ref temp_cate2);
                    if (temp_cate1.compareOther(temp_cate2) == false)
                    {
                        obj = "Category";
                        name = temp_cate1.principle + "<->" + temp_cate2.principle;
                        return false;
                    }
                }
                if (pAttribute.getLocalAttributeCount() != mLocalAttributeList.Count)
                {
                    obj = "LocalAttributes";
                    name = "LocalAttributeCount";
                    return false;
                }
                for (int i = 0; i < mLocalAttributeList.Count; i++)
                {
                    LocalAttribute temp_local1 = mLocalAttributeList[i];
                    LocalAttribute temp_local2 = new LocalAttribute();
                    pAttribute.getLocalAttribute(i, ref temp_local2);
                    if (temp_local1.compareOther(temp_local2) == false)
                    {
                        obj = "Category";
                        name = temp_local1.localType + "<->" + temp_local2.localType;
                        return false;
                    }
                }
                return true;
            }
        }
    }
}
